package com.cse.gpass;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.PointF;
import android.os.Vibrator;
import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class PasscodeView extends View{
	String TAG = "GESTURE";

	private int width;
	private int height;
	
	private int type;

	private String storedPass;
	private String password = "";
	private FileWriter fw;
	
	protected TextToSpeech tts;

	public PasscodeView(Context context, int width, int height, int type, Vibrator vr, TextToSpeech tts) {
		super(context);

		this.type = type;
		
		this.width = width;
		this.height = height;
		
		this.tts = tts;

		if(type == START || type == SETTING_WITH_PRE_PASS){
			Scanner console;
			FileReader fr;
			try {
				fr = new FileReader("/sdcard/gpassword.txt");
				console = new Scanner(fr);
				storedPass = "";
				if(console.hasNext()){
					storedPass = console.nextLine();
					Log.d("Read Password", storedPass);
				}
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			}
		}

		if(type == SETTING_WITHOUT_PRE_PASS || type == SETTING_WITH_PRE_PASS){
			try {
				fw = new FileWriter("/sdcard/gpassword.txt");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	private static int SETTING_WITHOUT_PRE_PASS = 0;
	private static int START = 1;
	private static int SETTING_WITH_PRE_PASS = 2;
	private static int CONFIRM = 3;

	static final int ONE_FINGER = 11;
	static final int TWO_FINGER = 12;
	static final int ONLY_FIRST = 13;
	static final int ONLY_SECOND = 14;
	static final int NONE = 15;
	int mode = NONE;
	
	

	PointF startPoint1 = new PointF();
	PointF endPoint1 = new PointF();
	PointF startPoint2 = new PointF();
	PointF endPoint2 = new PointF();

	@Override
	public boolean onTouchEvent(MotionEvent event){

		switch(event.getActionMasked()){
		case MotionEvent.ACTION_DOWN:
			startPoint1.set(event.getX(0), event.getY(0));
			Log.d(TAG, "mode=ONE FINGER");
			mode = ONE_FINGER;
			break;
		case MotionEvent.ACTION_POINTER_DOWN:
			startPoint2.set(event.getX(1), event.getY(1));
			Log.d(TAG, "mode=Two FINGER");
			mode = TWO_FINGER;
			break;
		case MotionEvent.ACTION_UP:

			//reorder later
			if (mode == ONLY_FIRST){
				endPoint1.set(event.getX(), event.getY());
				twoFinger();
			}else if (mode == ONLY_SECOND){
				endPoint2.set(event.getX(), event.getY());
				twoFinger();
			}else{ //mode = ONE_FINGER
				endPoint1.set(event.getX(), event.getY());
				oneFinger();
			}
			Log.d(TAG, "mode=NONE");
			mode = NONE;
			break;			
		case MotionEvent.ACTION_POINTER_UP:
			if (event.getActionIndex() == 1){
				endPoint2.set(event.getX(1), event.getY(1));
				Log.d(TAG, "mode=ONLY FIRST");		
				mode = ONLY_FIRST;
			}else if (event.getActionIndex() == 0){
				endPoint1.set(event.getX(0), event.getY(0));
				Log.d(TAG, "mode=ONLY SECOND");
				mode = ONLY_SECOND;
			}
			break;
		}
		return true;
	}

	private void oneFinger(){
		int stroke = eachStroke(startPoint1, endPoint1);
		if (stroke != 0 && stroke != 3){
			password += Math.abs(stroke);
			Log.d(TAG, Math.abs(stroke)+"");
		}
	}

	private void twoFinger(){
		int stroke1 = eachStroke(startPoint1, endPoint1);
		int stroke2 = eachStroke(startPoint2, endPoint2);
		int stroke2WithoutDirection = Math.abs(stroke2);
		int stroke1WithoutDirection = Math.abs(stroke1);
		//reorder later
		if (stroke1 == 0){			 
			if (stroke2WithoutDirection == 1){
				password += "9";
				Log.d(TAG, "9");
			}else if (stroke2WithoutDirection == 2){
				password += "10";
				Log.d(TAG, "10");
			}else{
				if(type == SETTING_WITHOUT_PRE_PASS){
					try {
						fw.write(password);
						Log.d("password", password + " -0");
						tts.speak("New passcode is created, please confirm it" +
								"tap the screen with your second finger while your" +
								"first finger is still on the screen",
								TextToSpeech.QUEUE_FLUSH, null);//change the text
						fw.close();
						type = 3;
						getPass(type);
						password = "";
					} catch (IOException e) {
						e.printStackTrace();
					}					
				//require heavy rework
				}else if(type == START || type == SETTING_WITH_PRE_PASS || type == CONFIRM){
					if(checkPass(password)){
						password = "";
						Log.d("password", "true");
						
						if(type == START){
							tts.speak("Passcode is solved, back to phone main menu",
									TextToSpeech.QUEUE_FLUSH, null);
							Intent toMain = new Intent(Intent.ACTION_MAIN);
							toMain.addCategory(Intent.CATEGORY_HOME);
							toMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
							
							((Activity)getContext()).startActivity(toMain);
						}else if(type == SETTING_WITH_PRE_PASS){
							String longSpeech ="Passcode solved. Now search the starting " +
							"corner of your new passcode. Once you find starting corner, start" +
							"by tapping the screen with your second finger while your first finger" +
							"remains on the screen";
							tts.speak(longSpeech, TextToSpeech.QUEUE_FLUSH, null);
							type = 0;
						}else{
							Log.d("password", password + " -0");
							tts.speak("Passcode is confirmed, back to B pass main menu",
									TextToSpeech.QUEUE_FLUSH, null);
								
							System.exit(0);
							 
						}
					}else{
						password = "";
						tts.speak("Incorrect passcode, please try again",
								TextToSpeech.QUEUE_FLUSH, null);
					}
					Log.d("password", password + " -1");
				}
			}
		}else if (stroke2 == 0){			 
			if (stroke1WithoutDirection == 1){
				password += "9";
				Log.d(TAG, "9");
			}else if (stroke1WithoutDirection == 2){
				password += "10";
				Log.d(TAG, "10");
			}
		}else{
			if ((stroke1WithoutDirection == 1) || (stroke2WithoutDirection == 1)){	// both horizontal
				if (stroke1 == stroke2){	//same direction
					password += "3";
					Log.d(TAG, "3");
				}else{	//opposite direction
					int yDirections = getMoveDirection(startPoint1.y, startPoint2.y, 
							endPoint1.y, endPoint2.y);
					if (yDirections == 1){
						password += "4";
						Log.d(TAG, "4");
					}else if (yDirections == -1){
						password += "5";
						Log.d(TAG, "5");
					}
				}
			}else if ((stroke1WithoutDirection == 2) || (stroke2WithoutDirection == 2)){	//both vertical
				if (stroke1 == stroke2){	//same direction
					password += "6";
					Log.d(TAG, "6");
				}else{	//opposite direction
					int xDirections = getMoveDirection(startPoint1.x, startPoint2.x, 
							endPoint1.x, endPoint2.x);
					if (xDirections == 1){
						password += "7";
						Log.d(TAG, "7");
					}else if (xDirections == -1){
						password += "8";
						Log.d(TAG, "8");
					}
				}
			}
		}			
	}

	//retruns -1 if two points are going closer
	//1 if two points are going further
	//0 if no change using Euclidean distance
	private int getMoveDirection(float startPoint1, float startPoint2, float endPoint1, float endPoint2){
		float startPointDiff = startPoint1 - startPoint2;
		float endPointDiff = endPoint1 - endPoint2;
		if (startPointDiff > endPointDiff)
			return -1;
		if (startPointDiff < endPointDiff)
			return 1;
		return 0;
	}

	//returns -1 if going vertically upward, 1 if going vertically downward,
	//-2 if going horizontally left, 2 if going horizontally right
	//0 if it wasn't moving, 3 otherwise
	private int eachStroke(PointF startPoint, PointF endPoint){
		//change these shits later
		float xError = width / 7;
		float yError = height / 11;
		float xDiffer = endPoint.x - startPoint.x;
		float yDiffer = endPoint.y - startPoint.y;

		float absXDiffer = Math.abs(xDiffer);
		float absYDiffer = Math.abs(yDiffer);
		if (absXDiffer <= xError){
			if (absYDiffer <= yError)
				return 0;
			if (yDiffer > 0)
				return 1;
			return -1;
		}
		if (absYDiffer <= yError){
			if (xDiffer > 0)
				return 2;
			return -2;	
		}
		if (absYDiffer > absXDiffer * 1.7){
			if (yDiffer > 0)
				return 1;
			return -1;
		}
		if (absXDiffer > absYDiffer * 1.7){
			if (xDiffer > 0)
				return 2;
			return -2;
		}
		return 3;
	}
	
	public void getPass(int type){
		if(type == 1 || type == 2 || type == 3){
			Scanner console;
			FileReader fr;
			try {
				fr = new FileReader("/sdcard/gpassword.txt");
				console = new Scanner(fr);
				storedPass = "";
				if(console.hasNext()){
					storedPass = console.nextLine();
					Log.d("Read Password", storedPass);
				}
			} catch (FileNotFoundException e1) {
				e1.printStackTrace();
			}
		}
	}

	public boolean checkPass(String password){
		Log.d("password", password);
		return password.equals(storedPass);
	}
}
